import { across, bet, tower } from '@prisma/client'
import { AcrossService } from 'src/across/across.service'
import { BetService } from 'src/bet/bet.service'
import { CalculateAcrossService } from 'src/calculate-across/calculate-across.service'
import { CalculateTowerService } from 'src/calculate-tower/calculate-tower.service'
import { calcAngle, calcF, calcFB, calcHi, calcTAFromTB, calcTBFromFB } from 'src/section/utils/ljImageMath'
import { TowerService } from 'src/tower/tower.service'
import { WireService } from 'src/wire/wire.service'
import { OrderService } from '../order.service'

/**
 * 采用模板设计模式修改计算代码
 */
export abstract class AbstractCalculate {
  constructor(
    private towers: TowerService,
    private bets: BetService,
    private across: AcrossService,
    private wire: WireService,
    private order: OrderService,
    private calcTower: CalculateTowerService,
    private calcAcross: CalculateAcrossService,
  ) {}

  public async calc(id: number) {
    if (await this.isCalculated(id)) return
    const { sectionId, w, w0, m, e } = await this.readData(id)
    const { lst_tower, lst_bet, lst_across } = await this.getListData(sectionId)
    const { lst_bet: lst_new_bet, lst_across: lst_new_across } = this.adjustOrder(lst_bet, lst_across)
    // 5. 计算控制点的受力情况-出口张力
    const lst = this.calcAcross.calculate({
      lst_tower,
      lst_bet: lst_new_bet,
      lst_across: lst_new_across,
      w,
      e,
      orderId: id,
    })

    // 6. 将数据存入数据库
    for (const item of lst) {
      await this.calcAcross.create({
        acrossId: item.acrossId,
        TT: item.TT,
        orderId: id,
        FB: item.FB,
        Hi: item.Hi,
        rank: item.rank,
      })
    }

    // 6. 将数据根据出口张力TT排序
    // await this.calcAcross.setRank({ orderId: id })
    // 7. 计算张力整定值
    // await this.calcTi(id)
    // 8. 计算铁塔受力
    // 9. 将张力整定值和最大牵引力写入order对象中
  }

  // 1. 判断是否已计算过，如果已计算过，则直接返回
  private async isCalculated(id: number) {
    const lst_calc_tower = await this.calcTower.findAll({ orderId: id })
    if (lst_calc_tower.length !== 0) return true
  }

  // 2. 读取order参数数据
  private async readData(id: number) {
    // 获取order所在的sectionId
    const order = await this.order.findOne(id)
    const sectionId = order.sectionId

    const w = (await this.wire.findOne(order.daoYinWireId)).wireWeight
    const w0 = (await this.wire.findOne(order.qianYinWireId)).wireWeight
    const m = order.wireNum
    const e = order.moZuNum

    return { sectionId, w, w0, m, e }
  }

  // 3. 获取sectionId的集合列表
  private async getListData(sectionId: number) {
    const lst_tower = await this.towers.findAll({ sectionId })
    const lst_bet = await this.bets.findAll({ sectionId })
    const lst_across = await this.across.findAll({ sectionId })

    return { lst_tower, lst_bet, lst_across }
  }

  // 4. 调整顺序，如果是逆向计算，则需要反转数据
  abstract adjustOrder(lst_bet: bet[], lst_across: across[]): { lst_bet: bet[]; lst_across: across[] }

  // 5. 计算张力整定值
  // async calcTi(id: number) {
  //   const lst_calc_across = await this.calcAcross.findAll({ orderId: id })
  //   const calc_across_max = lst_calc_across.find((ca) => ca.rank === 1)
  //   const Ti = calc_across_max.TT
  //   return Ti
  // }
}
